/**
 * APIJSON转换器 - 完整支持APIJSON语法
 * 版本：2.0
 * 最后更新：2025-05-07
 * 功能：
 * - 支持所有APIJSON查询语法
 * - 支持复杂嵌套查询
 * - 支持所有条件运算符
 * - 支持函数表达式
 * - 支持子查询
 */
class APIJSON转换器 {
  constructor() {
    this.运算符映射 = {
      '{}': 'IN',
      '{}=': 'IN',
      '{}!': 'NOT IN',
      '{}<>': 'NOT IN',
      '{}&': 'BETWEEN',
      '{}|': 'OR',
      '{}^': 'XOR',
      '~': 'LIKE',
      '!~': 'NOT LIKE',
      '~~': 'REGEXP',
      '!~~': 'NOT REGEXP',
      '>': '>',
      '>=': '>=',
      '<': '<',
      '<=': '<=',
      '=': '=',
      '!=': '!=',
      '<>': '<>'
    };
  }

  转换为SQL(APIJSON数据, 生成方法) {
    try {
      const 结果 = { 原始数据: APIJSON数据 };

      switch (生成方法) {
        case "查询":
          结果.查询SQL = this.生成查询语句(APIJSON数据);
          break;
        case "新增":
          结果.新增SQL = this.生成新增语句(APIJSON数据);
          break;
        case "修改":
          结果.修改SQL = this.生成修改语句(APIJSON数据);
          break;
        case "删除":
          结果.删除SQL = this.生成删除语句(APIJSON数据);
          break;
        default:
          throw new Error(`不支持的生成方法: ${生成方法}`);
      }

      return 结果;
    } catch (错误) {
      console.error('APIJSON转换错误:', 错误);
      throw new Error(`APIJSON转换失败: ${错误.message}`);
    }
  }

  // === 查询语句生成 ===
  生成查询语句(查询条件) {
      // 先处理字段引用
    for (const 表名 in 查询条件) {
        if (表名.startsWith('@')) continue;
        
        const 表条件 = 查询条件[表名];
        for (const 字段 in 表条件) {
            if (字段.endsWith('@')) {
                // 处理字段引用
                const 引用路径 = 表条件[字段];
                const [来源表, 来源字段] = 引用路径.split('/');
                
                if (!查询条件[来源表]) {
                    throw new Error(`引用表${来源表}不存在`);
                }
                
                // 将引用转换为关联条件
                if (!查询条件['@join']) {
                    查询条件['@join'] = {};
                }
                
                查询条件['@join'][来源表] = {
                    '@on': `${字段.replace('@', '')}/${来源字段}`
                };
                
                // 保留引用值
                表条件[字段.replace('@', '')] = 查询条件[来源表][来源字段];
            }
        }
    }

   
    // 处理带[]的查询结构
    if (查询条件['[]']) {
      return this.处理分页查询(查询条件['[]']);
    }

    // 处理普通查询
    let SQL = 'SELECT ';
    const 表名 = Object.keys(查询条件).find(键 => !['@column', '@group', '@order', '@having', '@distinct', '@join'].includes(键));
    
    // 处理字段选择
    SQL += this.处理字段选择(查询条件);

    // 主表
    SQL += ` FROM ${表名}`;

    // 处理关联查询
    if (查询条件['@join']) {
      console.log('处理关联表');
      SQL += this.处理关联表(查询条件['@join'], 表名);
    }

    // 处理条件
    const 条件语句 = this.生成条件子句(查询条件[表名]);
    if (条件语句) SQL += ` WHERE ${条件语句}`;

    // 处理分组
    if (查询条件['@group']) {
      SQL += ` GROUP BY ${查询条件['@group'].join(', ')}`;
    }

    // 处理HAVING
    if (查询条件['@having']) {
      SQL += ` HAVING ${this.生成条件子句(查询条件['@having'])}`;
    }

    // 处理排序
    if (查询条件['@order']) {
      SQL += ` ORDER BY ${this.处理排序条件(查询条件['@order'])}`;
    }

    // 处理分页
    if (查询条件['@limit']) {
      SQL += this.处理分页参数(查询条件['@limit']);
    }

    return SQL;
  }

  处理分页查询(分页配置) {
    const 表名 = Object.keys(分页配置).find(键 => 键 !== 'count' && 键 !== 'page' && 键 !== 'query' && !键.endsWith('[]'));
    
    if (!表名) {
      throw new Error('无效的分页查询结构：未指定表名');
    }

    // 处理嵌套数组查询
    const 嵌套数组查询 = {};
    for (const 键 in 分页配置) {
      if (键.endsWith('[]')) {
        嵌套数组查询[键] = 分页配置[键];
      }
    }

    const 表配置 = 分页配置[表名] || {};
    const 查询配置 = 分页配置.query || {};
    
    let SQL = 'SELECT ';
    
    // 处理字段选择
    SQL += this.处理字段选择(Object.assign({}, 表配置, 查询配置));

    // 主表
    SQL += ` FROM ${表名}`;

    // 处理关联查询
    if (表配置['@join'] || 查询配置['@join']) {
      SQL += this.处理关联表(Object.assign({}, 表配置['@join'], 查询配置['@join']), 表名);
    }

    // 处理引用关系
    SQL += this.处理引用关系(表配置, 表名, 嵌套数组查询);

    // 处理条件
    const 条件语句 = this.生成条件子句(Object.assign({}, 表配置, 查询配置));
    if (条件语句) SQL += ` WHERE ${条件语句}`;

    // 处理分组、排序等
    if (表配置['@group'] || 查询配置['@group']) {
      SQL += ` GROUP BY ${(表配置['@group'] || 查询配置['@group']).join(', ')}`;
    }

    if (表配置['@having'] || 查询配置['@having']) {
      SQL += ` HAVING ${this.生成条件子句(Object.assign({}, 表配置['@having'], 查询配置['@having']))}`;
    }

    if (表配置['@order'] || 查询配置['@order']) {
      SQL += ` ORDER BY ${this.处理排序条件(Object.assign({}, 表配置['@order'], 查询配置['@order']))}`;
    }

    // 处理分页
    SQL += this.处理分页参数({
      数量: 分页配置.count,
      页码: 分页配置.page
    });

    return SQL;
}

处理引用关系(表配置, 表名, 嵌套数组查询) {
  let 关联语句 = '';
  
  // 处理当前表的引用
  for (const 字段 in 表配置) {
      if (字段.endsWith('@')) {
          const 引用路径 = 表配置[字段];
          const [来源表, 来源字段] = 引用路径.split('/');
          
          关联语句 += ` JOIN ${来源表} ON ${表名}.${字段.replace('@', '')}=${来源表}.${来源字段}`;
      }
  }
  
  // 处理嵌套数组查询的引用
  for (const 嵌套查询名 in 嵌套数组查询) {
      const 嵌套配置 = 嵌套数组查询[嵌套查询名];
      const 嵌套表名 = 嵌套查询名.replace('[]', '');
      
      for (const 字段 in 嵌套配置[嵌套表名]) {
          if (字段.endsWith('@')) {
              const 引用路径 = 嵌套配置[嵌套表名][字段];
              const 路径部分 = 引用路径.split('/');
              
              if (路径部分[0] === '[]') {
                  // 引用父表
                  关联语句 += ` LEFT JOIN ${嵌套表名} ON ${表名}.${路径部分[2]}=${嵌套表名}.${字段.replace('@', '')}`;
              } else {
                  // 引用其他表
                  关联语句 += ` LEFT JOIN ${嵌套表名} ON ${路径部分[0]}.${路径部分[1]}=${嵌套表名}.${字段.replace('@', '')}`;
              }
          }
      }
  }
  
  return 关联语句;
}

  // === 增删改语句生成 ===
  生成新增语句(新增数据) {
    const 表名 = Object.keys(新增数据)[0];
    const 字段列表 = [];
    const 值列表 = [];

    for (const 字段 in 新增数据[表名]) {
      if (字段.startsWith('@')) continue; // 跳过指令字段
      字段列表.push(字段);
      值列表.push(this.格式化SQL值(新增数据[表名][字段]));
    }

    return `INSERT INTO ${表名} (${字段列表.join(', ')}) VALUES (${值列表.join(', ')})`;
  }

  生成修改语句(修改数据) {
    const 表名 = Object.keys(修改数据)[0];
    const 更新项 = [];
    const 条件项 = [];

    for (const 字段 in 修改数据[表名]) {
      if (字段.startsWith('@')) continue; // 跳过指令字段
      
      if (this.是条件字段(字段)) {
        条件项.push(this.处理条件字段(字段, 修改数据[表名][字段]));
      } else {
        更新项.push(`${字段} = ${this.格式化SQL值(修改数据[表名][字段])}`);
      }
    }

    let SQL = `UPDATE ${表名} SET ${更新项.join(', ')}`;
    if (条件项.length) SQL += ` WHERE ${条件项.join(' AND ')}`;

    return SQL;
  }

  生成删除语句(删除数据) {
    const 表名 = Object.keys(删除数据)[0];
    const 条件项 = [];

    for (const 字段 in 删除数据[表名]) {
      if (字段.startsWith('@')) continue; // 跳过指令字段
      条件项.push(this.处理条件字段(字段, 删除数据[表名][字段]));
    }

    let SQL = `DELETE FROM ${表名}`;
    if (条件项.length) SQL += ` WHERE ${条件项.join(' AND ')}`;

    return SQL;
  }

  // === 辅助方法 ===
  处理字段选择(配置) {
    if (配置['@column']) {
      if (Array.isArray(配置['@column'])) {
        return 配置['@column'].join(', ');
      }
      return 配置['@column'];
    }
    
    if (配置['@distinct']) {
      return `DISTINCT ${配置['@distinct'].join(', ')}`;
    }
    
    return '*';
  }
  处理关联表(关联配置, 主表名) {
    let 关联语句 = '';
    let 别名计数 = 0;
    
    for (const 关联表 in 关联配置) {
      const 配置 = 关联配置[关联表];
      const 关联类型 = 配置['@type'] || 'LEFT JOIN'; // 默认使用LEFT JOIN
      const 别名 = 配置['@alias'] || `t${++别名计数}`;
      
      // 处理自连接情况
      const 目标表名 = (关联表 === 主表名) ? `${关联表} ${别名}` : 关联表;
      
      关联语句 += ` ${关联类型} ${目标表名}`;
      if (配置['@on']) {
        const [主表字段, 关联表字段] = 配置['@on'].split('/');
        关联语句 += ` ON ${主表名}.${主表字段}=${别名}.${关联表字段}`;
      }
    }
    return 关联语句;
}
  
  

  生成条件子句(条件对象) {
    if (!条件对象) return '';
    
    const 条件列表 = [];
    
    for (const 字段 in 条件对象) {
      if (字段.startsWith('@')) continue; // 跳过指令字段
      
      const 条件值 = 条件对象[字段];
      
      if (typeof 条件值 === 'object' && !Array.isArray(条件值)) {
        // 处理嵌套条件
        条件列表.push(this.处理嵌套条件(字段, 条件值));
      } else {
        // 处理普通条件
        条件列表.push(this.处理条件字段(字段, 条件值));
      }
    }
    
    return 条件列表.join(' AND ');
  }

  处理嵌套条件(字段, 条件对象) {
    const 嵌套条件 = [];
    
    for (const 操作符 in 条件对象) {
      const 值 = 条件对象[操作符];
      const SQL操作符 = this.运算符映射[操作符];
      
      if (!SQL操作符) {
        throw new Error(`不支持的操作符: ${操作符}`);
      }
      
      if (操作符 === '{}&') {
        // BETWEEN 处理
        if (!Array.isArray(值) || 值.length !== 2) {
          throw new Error('BETWEEN 操作需要两个值的数组');
        }
        嵌套条件.push(`${字段} BETWEEN ${this.格式化SQL值(值[0])} AND ${this.格式化SQL值(值[1])}`);
      } else if (操作符 === '{}|') {
        // OR 条件
        if (typeof 值 === 'object') {
          const OR条件 = [];
          for (const OR字段 in 值) {
            OR条件.push(this.处理条件字段(OR字段, 值[OR字段]));
          }
          嵌套条件.push(`(${OR条件.join(' OR ')})`);
        }
      } else {
        // 其他操作符
        嵌套条件.push(`${字段} ${SQL操作符} ${this.处理操作符值(SQL操作符, 值)}`);
      }
    }
    
    return 嵌套条件.join(' AND ');
  }

  处理条件字段(字段名, 值) {
    // 处理函数表达式
    if (字段名.includes('@')) {
      return this.处理函数表达式(字段名, 值);
    }
    
    // 处理范围查询
    if (this.是条件字段(字段名)) {
      return this.处理范围条件(字段名, 值);
    }
    
    // 处理普通条件
    return `${字段名} = ${this.格式化SQL值(值)}`;
  }

  是条件字段(字段名) {
    return /[{}$!~^|&]/.test(字段名);
  }

  处理范围条件(字段名, 范围值) {
    const 操作符 = this.提取操作符(字段名);
    const 真实字段 = 字段名.replace(/[{}!$~^|&=<>]/g, '');
    const SQL操作符 = this.运算符映射[操作符];
    
    if (!SQL操作符) {
      throw new Error(`不支持的操作符: ${操作符}`);
    }
    
    if (操作符 === '{}&') {
      // BETWEEN 处理
      if (!Array.isArray(范围值) || 范围值.length !== 2) {
        throw new Error('BETWEEN 操作需要两个值的数组');
      }
      return `${真实字段} BETWEEN ${this.格式化SQL值(范围值[0])} AND ${this.格式化SQL值(范围值[1])}`;
    }
    
    if (操作符 === '{}|') {
      // OR 条件
      if (typeof 范围值 === 'object') {
        const OR条件 = [];
        for (const OR字段 in 范围值) {
          OR条件.push(this.处理条件字段(OR字段, 范围值[OR字段]));
        }
        return `(${OR条件.join(' OR ')})`;
      }
    }
    
    return `${真实字段} ${SQL操作符} ${this.处理操作符值(SQL操作符, 范围值)}`;
  }

  提取操作符(字段名) {
    if (字段名.includes('{}!')) return '{}!';
    if (字段名.includes('{}=')) return '{}=';
    if (字段名.includes('{}<>')) return '{}<>';
    if (字段名.includes('{}&')) return '{}&';
    if (字段名.includes('{}|')) return '{}|';
    if (字段名.includes('{}^')) return '{}^';
    if (字段名.includes('~')) return '~';
    if (字段名.includes('!~')) return '!~';
    if (字段名.includes('~~')) return '~~';
    if (字段名.includes('!~~')) return '!~~';
    if (字段名.includes('>=')) return '>=';
    if (字段名.includes('<=')) return '<=';
    if (字段名.includes('>')) return '>';
    if (字段名.includes('<')) return '<';
    if (字段名.includes('!=')) return '!=';
    if (字段名.includes('<>')) return '<>';
    return '=';
  }

  处理操作符值(操作符, 值) {
    if (操作符 === 'IN' || 操作符 === 'NOT IN') {
      if (!Array.isArray(值)) {
        值 = 值.split(',');
      }
      return `(${值.map(v => this.格式化SQL值(v.trim())).join(', ')})`;
    }
    
    if (操作符 === 'LIKE' || 操作符 === 'NOT LIKE') {
      return `'%${值}%'`;
    }
    
    return this.格式化SQL值(值);
  }

  处理函数表达式(字段名, 值) {
    const [函数名, 参数] = 字段名.split('@');
    
    if (!函数名 || !参数) {
      throw new Error(`无效的函数表达式: ${字段名}`);
    }
    
    const 支持的函数 = ['SUM', 'COUNT', 'AVG', 'MAX', 'MIN', 'CONCAT', 'DATE_FORMAT'];
    
    if (!支持的函数.includes(函数名.toUpperCase())) {
      throw new Error(`不支持的函数: ${函数名}`);
    }
    
    return `${函数名}(${参数}) = ${this.格式化SQL值(值)}`;
  }

  处理排序条件(排序配置) {
    if (typeof 排序配置 === 'string') {
      return 排序配置;
    }
    
    const 排序项 = [];
    
    for (const 字段 in 排序配置) {
      const 方向 = 排序配置[字段] === 'DESC' ? 'DESC' : 'ASC';
      排序项.push(`${字段} ${方向}`);
    }
    
    return 排序项.join(', ');
  }

  处理分页参数(分页配置) {
    const 每页条数 = 分页配置.数量 || (分页配置.count || 10);
    const 偏移量 = 分页配置.页码 ? (分页配置.页码 - 1) * 每页条数 : 0;
    return ` LIMIT ${每页条数} OFFSET ${偏移量}`;
  }

  格式化SQL值(值) {
    if (值 === null || 值 === undefined) return 'NULL';
    if (typeof 值 === 'boolean') return 值 ? 'TRUE' : 'FALSE';
    if (typeof 值 === 'number') return 值;
    if (typeof 值 === 'string') {
      if (值.startsWith('@')) {
        // 处理表达式
        return 值.substring(1);
      }
      return `'${值.replace(/'/g, "''")}'`;
    }
    if (Array.isArray(值)) {
      return `(${值.map(this.格式化SQL值.bind(this)).join(', ')})`;
    }
    if (typeof 值 === 'object') {
      return `'${JSON.stringify(值).replace(/'/g, "''")}'`;
    }
    return 值;
  }
}

module.exports = APIJSON转换器;

